home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
exampleCode
/
opengl
/
extensions
/
samples
/
videotogfx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-11
|
14KB
|
468 lines
/*
* Copyright (c) 1994 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that (i) the above copyright notices and this permission
* notice appear in all copies of the software and related documentation,
* and (ii) the name of Silicon Graphics may not be used in any
* advertising or publicity relating to the software without the specific,
* prior written permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
* INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
/*
* vidtogfx.c
* This VL program demonstrates the Sirius Video board video->graphics ability
* using OpenGL.
*
* See the usage() function for the command line options (or run with -h).
*
* $Revision: 1.1 $
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <device.h>
#include <vl/vl.h>
#include <vl/dev_sirius.h>
#include <GL/glx.h>
#include "xwindow.h"
#include <X11/keysym.h>
/* VL variable */
VLControlValue size, timing, dominance;
VLControlValue format;
VLServer svr;
VLPath path;
VLNode src;
VLNode drn;
int F1_is_first; /* Which field is first */
/* OpenGL/X variables */
Display *dpy;
Window window;
#ifdef GLX_SGIX_video_source
GLXVideoSourceSGIX glxVideoSource;
#else /* Make the compiler barf */
GLX_SGIX_video_source is not defined in this version of the library
#endif
GLXContext ctx;
GLfloat zoom = 1;
GLboolean interlace = GL_FALSE;
/* Interlace extension is (partially or fully) implemented */
GLboolean hasInterlace;
/*
* function prototypes
*/
void usage(char *, int);
void InitGfx(int, char **);
void GrabField(int);
void UpdateTiming(void);
void cleanup(void);
void ProcessEvents(void);
static void loop(void);
int
main(int argc, char **argv)
{
int c, insrc = VL_ANY;
int device = VL_ANY;
short dev, val;
/* Parse the input string */
while ((c = getopt(argc, argv, "n:v:h")) != EOF ) {
switch (c) {
case 'n':
device = atoi(optarg); /* user can override default device */
break;
case 'v':
insrc = atoi(optarg); /* Check to see input node */
break;
case 'h':
usage(argv[0], EXIT_SUCCESS);
default:
usage(argv[0], EXIT_FAILURE);
}
}
/* open connection to VL server */
if (!(svr = vlOpenVideo(""))) {
printf("couldn't open connection to VL server\n");
exit(EXIT_FAILURE);
}
/* Get the Video input */
src = vlGetNode(svr, VL_SRC, VL_VIDEO, insrc);
/* Get the first Graphics output */
drn = vlGetNode(svr, VL_DRN, VL_GFX, 0);
/* Create path */
path = vlCreatePath(svr, device, src, drn);
if (path < 0) {
vlPerror("vlCreatePath");
exit(EXIT_FAILURE);
}
/* Setup path */
if (vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE) < 0) {
vlPerror("vlSetupPaths");
exit(EXIT_FAILURE);
}
UpdateTiming();
if (vlSelectEvents(svr, path,VLStreamPreemptedMask |
VLControlChangedMask ) < 0) {
vlPerror("Select Events");
exit(EXIT_FAILURE);
}
/* Open the GL window for gfx transfers */
InitGfx(argc, argv);
/* Begin Transfers */
vlBeginTransfer(svr, path, 0, NULL);
/* The following sequence grabs each field and displays it in
* the GL window.
*/
loop();
}
void
loop()
{
XEvent event;
KeySym key;
XComposeStatus compose;
GLboolean clearNeeded = GL_FALSE;
while (GL_TRUE) {
while(XPending(dpy)) {
XNextEvent(dpy, &event);
switch(event.type) {
case KeyPress:
XLookupString(&event.xkey, NULL, 0, &key, NULL);
switch (key) {
case XK_Escape:
exit(EXIT_SUCCESS);
case XK_z:
zoom = 3 - zoom; /* 2 -> 1, 1 -> 2 */
XMoveResizeWindow(dpy, window, 50, 0,
zoom * size.xyVal.x, zoom * size.xyVal.y);
glXWaitX();
glLoadIdentity();
glViewport(0, 0, zoom * size.xyVal.x - 1,
zoom * size.xyVal.y - 1);
glOrtho(0, zoom * size.xyVal.x - 1,
0, zoom * size.xyVal.y - 1, -1, 1);
clearNeeded = GL_TRUE;
break;
case XK_i:
if (hasInterlace) {
interlace = !interlace;
if (!interlace) {
if (!glXMakeCurrentReadSGI(dpy, window,
glxVideoSource, ctx)) {
fprintf(stderr,
"Can't make current to video\n");
exit(EXIT_FAILURE);
}
} else if (!glXMakeCurrent(dpy, window, ctx)) {
fprintf(stderr,
"Can't make window current to context\n");
exit(EXIT_FAILURE);
}
clearNeeded = GL_TRUE;
printf("Interlace is %s\n", interlace ? "On" : "Off");
} else {
printf("Graphics interlacing is not supported\
by on this renderer\n");
}
break;
case XK_question:
case XK_h:
printf("Keys:\tz - toggle zoom (of 2)\n");
printf("\ti - toggle interlacing/zooming of fields\n");
printf("\th/? - print help\n");
printf("\tEsc - exit\n");
}
break;
}
}
if (clearNeeded) {
glClear(GL_COLOR_BUFFER_BIT);
glXSwapBuffers(dpy, window);
glClear(GL_COLOR_BUFFER_BIT);
glXSwapBuffers(dpy, window);
clearNeeded = GL_FALSE;
glPixelZoom(zoom, -2 * zoom);
glRasterPos2f(0, zoom * size.xyVal.y - 1);
}
ProcessEvents();
GrabField(0);
glXSwapBuffers(dpy, window);
GrabField(1);
glXSwapBuffers(dpy, window);
}
}
void
usage(char *name, int exitStatus)
{
fprintf(stderr, "usage: %s [-n#] [-v#] [-h (for help)]\n", name);
fprintf(stderr, "\t-n# video device number (as reported by vlinfo)\n");
fprintf(stderr, "\t-v# video input number (as reported by vlinfo)\n");
fprintf(stderr,
"\tInteractively, `h/?' keys provide description of interface\n");
exit(exitStatus);
}
/*
* Open an X window of appropriate size and create context.
*/
void
InitGfx(int argc, char **argv)
{
int i;
XSizeHints hints;
int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 12,
GLX_GREEN_SIZE, 12, GLX_BLUE_SIZE, 12,
GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0,
None};
const char *extensions;
hints.x = 50; hints.y = 0;
hints.min_aspect.x = hints.max_aspect.x = size.xyVal.x;
hints.min_aspect.y = hints.max_aspect.y = size.xyVal.y;
hints.min_width = size.xyVal.x;
hints.max_width = 3 * size.xyVal.x;
hints.base_width = hints.width = size.xyVal.x;
hints.min_height = size.xyVal.y;
hints.max_height = 3 * size.xyVal.y;
hints.base_height = hints.height = size.xyVal.y;
hints.flags = USSize | PAspect | USPosition | PMinSize | PMaxSize;
createWindowAndContext(&dpy, &window, &ctx, 50, 0, size.xyVal.x,
size.xyVal.y, GL_FALSE, &hints, visualAttr, argv[0]);
extensions = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
if (extensions == NULL ||
strstr(extensions, "GLX_SGI_make_current_read") == NULL) {
fprintf(stderr, "The make_current_read extension\
is not supported on this system\n");
exit(EXIT_FAILURE);
}
if (strstr(extensions, "GLX_SGIX_video_source") == NULL) {
fprintf(stderr, "The GLX video source extension\
is not supported on this system\n");
exit(EXIT_FAILURE);
}
glxVideoSource = glXCreateGLXVideoSourceSGIX(dpy, 0, svr, path,
VL_GFX, drn);
if (glxVideoSource == NULL) {
fprintf(stderr, "Can't create glxVideoSource\n");
exit(EXIT_FAILURE);
}
if (!glXMakeCurrentReadSGI(dpy, window, glxVideoSource, ctx)) {
fprintf(stderr, "Can't make current to video\n");
exit(EXIT_FAILURE);
}
glLoadIdentity();
glViewport(0, 0, zoom * size.xyVal.x, zoom * size.xyVal.y);
glOrtho(0, zoom * size.xyVal.x, 0, zoom * size.xyVal.y, -1, 1);
glPixelZoom(zoom, -2 * zoom);
glRasterPos2f(0, zoom * size.xyVal.y - 1);
glReadBuffer(GL_FRONT);
/*
* Check for interlace extension.
*/
hasInterlace =
strstr((const char *) extensions, "GL_SGIX_interlace") != NULL;
if (!hasInterlace) {
/*
* HACK - Interlace is not formally advertised. Try getting it anyhow.
*/
glDisable(GL_INTERLACE_SGIX);
hasInterlace = glGetError() == GL_NO_ERROR;
if (hasInterlace)
fprintf(stderr, "Assuming SGIX_Interlace supported but\
not advertised\n");
}
}
/*
* Grab a field. A parameter of 1 = odd Field, 0 = Even Field.
* Use the global F1_is_first variable to determine how to interleave the fields.
*/
void
GrabField(int odd_field)
{
/* copy pixels from front to back buffer */
if (interlace) {
/* Restore zoom and transfer mode */
glRasterPos2i(0, 0);
glPixelZoom(1, 1);
glCopyPixels(0, 0, size.xyVal.x * zoom, size.xyVal.y * zoom, GL_COLOR);
/* Copy the field from Sirius Video to GFX subsystem */
if (!glXMakeCurrentReadSGI(dpy, window, glxVideoSource, ctx)) {
fprintf(stderr, "Can't make current to video\n");
exit(EXIT_FAILURE);
}
if (odd_field) {
if (F1_is_first) {
/* F1 dominant, so odd field is first. */
glRasterPos2f(0, zoom * size.xyVal.y - 1);
} else {
/* F2 dominant, so even field is first. */
glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
}
} else {
if (F1_is_first) {
/* F1 dominant, so odd field is first. */
glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
} else {
/* F2 dominant, so even field is first. */
glRasterPos2f(0, zoom * size.xyVal.y - 1);
}
}
#ifdef GL_SGIX_interlace
glEnable(GL_INTERLACE_SGIX);
#endif
/* video is upside down relative to graphics */
glPixelZoom(zoom, -zoom);
glCopyPixels(0, 0, size.xyVal.x, size.xyVal.y/2, GL_COLOR);
if (!glXMakeCurrent(dpy, window, ctx)) {
fprintf(stderr, "Can't make current to original window\n");
exit(EXIT_FAILURE);
}
#ifdef GL_SGIX_interlace
glDisable(GL_INTERLACE_SGIX);
#endif
} else {
if (!odd_field) {
if (!F1_is_first) {
/* F1 dominant, so odd field is first. */
glRasterPos2f(0, zoom * size.xyVal.y - 1);
} else {
/* F2 dominant, so even field is first. */
glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
}
} else {
if (!F1_is_first) {
/* F1 dominant, so odd field is first. */
glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
} else {
/* F2 dominant, so even field is first. */
glRasterPos2f(0, zoom * size.xyVal.y - 1);
}
}
glCopyPixels(0, 0, size.xyVal.x, size.xyVal.y/2, GL_COLOR);
}
}
void
UpdateTiming(void)
{
int is_525;
/* Get the timing on selected input node */
if (vlGetControl(svr, path, src, VL_TIMING, &timing) <0) {
vlPerror("VlGetControl:TIMING");
exit(EXIT_FAILURE);
}
/* Set the GFX Drain to the same timing as input src */
if (vlSetControl(svr, path, drn, VL_TIMING, &timing) <0) {
vlPerror("VlSetControl:TIMING");
exit(EXIT_FAILURE);
}
if (vlGetControl(svr, path, drn, VL_SIZE, &size) <0) {
vlPerror("VlGetControl");
exit(EXIT_FAILURE);
}
/*
* Read the video source's field dominance control setting and timing,
* then set a variable to indicate which field has the first line, so that
* we know how to interleave fields to frames.
*/
if (vlGetControl(svr, path, src,
VL_SIR_FIELD_DOMINANCE, &dominance) < 0) {
vlPerror("GetControl(VL_SIR_FIELD_DOMINANCE) on video source failed");
exit(EXIT_FAILURE);
}
is_525 = ( (timing.intVal == VL_TIMING_525_SQ_PIX) ||
(timing.intVal == VL_TIMING_525_CCIR601) );
switch (dominance.intVal) {
case SIR_F1_IS_DOMINANT:
if (is_525) {
F1_is_first = 0;
} else {
F1_is_first = 1;
}
break;
case SIR_F2_IS_DOMINANT:
if (is_525) {
F1_is_first = 1;
} else {
F1_is_first = 0;
}
break;
}
}
void
cleanup(void)
{
vlEndTransfer(svr, path);
vlDestroyPath(svr, path);
vlCloseVideo(svr);
exit(EXIT_SUCCESS);
}
void
ProcessEvents(void)
{
VLEvent ev;
if (vlCheckEvent(svr, VLControlChangedMask|
VLStreamPreemptedMask, &ev) == -1) {
return;
}
switch(ev.reason) {
case VLStreamPreempted:
cleanup();
exit(EXIT_SUCCESS);
case VLControlChanged:
switch(ev.vlcontrolchanged.type) {
case VL_TIMING:
case VL_SIZE:
case VL_SIR_FIELD_DOMINANCE:
UpdateTiming();
/* change the gl window size */
XResizeWindow(dpy, window, zoom * size.xyVal.x, zoom * size.xyVal.y);
glXWaitX();
printf("Resizing\n");
glLoadIdentity();
glViewport(0, 0, zoom * size.xyVal.x, zoom * size.xyVal.y );
glOrtho(0, zoom * size.xyVal.x, 0, zoom * size.xyVal.y, -1, 1);
break;
default:
break;
}
break;
default:
break;
}
}